package com.hzlj.position.locate.differentiation.positionWarningNotice;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.hzlj.position.config.common.dto.common.PositionHandleExtDTO;
import com.hzlj.position.config.common.enums.WarningType;
import com.hzlj.position.config.service.NoticeConfigService;
import com.hzlj.position.locate.common.dto.position.PositionHandleDTO;
import com.hzlj.position.locate.common.dto.position.PositionKeyDTO;
import com.hzlj.position.locate.common.model.Position;
import com.hzlj.position.locate.differentiation.common.PositionWarningNoticeGzry;
import com.hzlj.position.locate.differentiation.common.PositionWarningNoticeJzry;
import com.hzlj.position.locate.differentiation.positionWarningHandle.PositionWarningHandleSxJc;
import com.hzlj.position.locate.service.PositionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 山西-晋城
 * 根据配置来做发送+处理异常
 */
@Slf4j
@Service
public class PositionWarningNoticeSxJc extends PositionWarningNotice {
    @Resource
    private PositionWarningNoticeJzry positionWarningNoticeJzry;
    @Resource
    private PositionWarningNoticeGzry positionWarningNoticeGzry;
    @Resource
    private PositionWarningHandleSxJc positionWarningHandleSxJc;
    @Resource
    private NoticeConfigService noticeConfigService;
    @Resource
    private RedisTemplate<String, Date> redisTemplate;
    @Resource
    private PositionService positionService;

    /**
     * locate:warning:notice:{gzry/jzry}:{jzId}:{yyyyMMdd}
     */
    private final static String SEND_DAY_KEY = "locate:warning:notice:%s:%s:%s";

    @Override
    public void noticeJzry(List<Position> positions) {
        Date now = new Date();

        //需要发送通知的类型
        positions = positions.stream()
                .filter(position -> noticeConfigService.warningJzryNotice(position.getJgCode(), position.getWarningType()))
                .filter(position -> filterNotice(now, "jzry", position))
                .collect(Collectors.toList());

        //发送
        positionWarningNoticeJzry.notice(positions);

        //缓存发送记录
        cacheNotice(now, "jzry", positions);
    }

    @Override
    public void noticeGzry(List<Position> positions) {
        Date now = new Date();

        //需要发送通知的类型
        positions = positions.stream()
                .filter(position -> noticeConfigService.warningGzryNotice(position.getJgCode(), position.getWarningType())).filter(position -> filterNotice(now, "gzry", position))
                .collect(Collectors.toList());
        //发送
        positionWarningNoticeGzry.notice(positions, this);

        //缓存发送记录
        cacheNotice(now, "gzry", positions);

        //处理
        List<Pair<Position, PositionHandleDTO>> pairs = positionWarningHandleSxJc.withHandle(positions);
        handle(
                pairs.stream().filter(handleFilter(now)).collect(Collectors.toList())
        );
    }


    private Predicate<Pair<Position, PositionHandleDTO>> handleFilter(Date now) {
        return e -> {
            return e.getValue() != null
                    && DateUtil.isSameDay(now, e.getValue().getHandleTime())
                    && Boolean.TRUE.equals(e.getValue().getHandleExt().getHandleAfter());
        };
    }

    private boolean filterNotice(Date now,
                                 String ryLx,
                                 Position position) {
        //6点
        Calendar start = Calendar.getInstance();
        start.setTime(DateUtil.beginOfDay(now));
        start.set(Calendar.HOUR_OF_DAY, 6);
        //22点
        Calendar end = Calendar.getInstance();
        end.setTime(DateUtil.beginOfDay(now));
        end.set(Calendar.HOUR_OF_DAY, 22);

        //不是越界
        if (!position.getWarningType().equals(WarningType.CROSS.getCode())) {
            return true;
        }
        //6-22点
        if (now.before(start.getTime()) || now.after(end.getTime())) {
            log.info("告警短信，不在6点和22点之间，不发送:position={}", position);
            return false;
        }
        //已经发送的不发送
        Date date = redisTemplate.opsForValue().get(cacheKey(now, ryLx, position));
        if (ObjectUtil.isNotEmpty(date)) {
            log.info("告警短信，当天已经存在发送记录，不发送:position={}", position);
            return false;
        }
        return true;
    }

    private void cacheNotice(Date now,
                             String ryLx,
                             List<Position> positions) {
        Map<String, Date> cacheKeys = positions.stream()
                .filter(position -> position.getWarningType().equals(WarningType.CROSS.getCode()))
                .map(position -> cacheKey(now, ryLx, position))
                .collect(Collectors.toMap(key -> key, key -> now));
        if (ObjectUtil.isEmpty(cacheKeys)) {
            return;
        }
        redisTemplate.opsForValue().multiSet(cacheKeys);
    }

    private String cacheKey(Date now,
                            String ryLx,
                            Position position) {
        return String.format(SEND_DAY_KEY, ryLx, position.getJzId(), DateUtil.format(now, "yyyyMMdd"));
    }

    /**
     * 根据上一次的处理结果处理
     */
    private void handle(List<Pair<Position, PositionHandleDTO>> handles) {
        if (ObjectUtil.isEmpty(handles)) {
            return;
        }
        Date now = new Date();
        for (Pair<Position, PositionHandleDTO> handle : handles) {
            Position position = handle.getKey();
            PositionHandleDTO value = handle.getValue();
            PositionHandleExtDTO ext = value.getHandleExt();
            if (ext == null) {
                ext = new PositionHandleExtDTO();
            }
            ext.setHandleTime(now);
            if (ObjectUtil.isEmpty(ext.getHandleRemark())) {
                ext.setHandleRemark("系统自动处理");
            } else {
                ext.setHandleRemark(ext.getHandleRemark() + "（系统自动处理）");
            }
            //需要打上系统处理标记
            value.setAutoHandle(true);
            value.setHandleTime(now);
            value.setFromOpenApi(null);
            value.setHandleExt(ext);
            value.setKeys(Lists.newArrayList(new PositionKeyDTO(position.getId(), position.getPositionTime())));
            positionService.handle(value);
        }
    }


}
